package tpcomp2010.estructura;

/**
 * Clase encargada de verificar si una cadena pertenece o no a un automata.
 *
 * @author Tania Nuñez
 * @autor Victor Ayala
 * 
 */

public class Simulacion {

   
    Automata elAutomata;

   
    TipoAutomata elTipoAutomata;

    
    String camino;

    /**
     * Class Constructor especificando el automata y el tipo de automata
     * @param elAutomata automata que se utiliza para hacer la simulacion
     * @param elTipoAutomata tipo de automata que maneja el simulador
     */
    public Simulacion(Automata elAutomata, TipoAutomata elTipoAutomata) {
        this.elAutomata = elAutomata;
        this.elTipoAutomata = elTipoAutomata;
    }

    /**
     * Realiza la simulacion
     * @param cadena entrada de prueba para la simulacion
     * @return true si el resultado de la simulacion es positivo, es decir, si la
     * cadena de entrada pertenece al lenguaje aceptado por el automata, false en
     * contrario
     */
    public boolean ejecutar(String cadena) {
        if (this.elTipoAutomata == TipoAutomata.AFN) {
            return simularAFN(cadena);
        } else {
            return simularAFD(cadena);
        }
    }

    /**
     * Simula, dada una cadena de entrada, el AFN que se representa por la propiedad
     * elAutomata
     * @param cadena entrada para la simulacion
     * @return true si la cadena pertenece al AFN, false en caso contrario
     */
    private boolean simularAFN(String cadena) {
        ListaNodos s;
        camino = "\nCamino: ";

        s = SubConjunto.e_cerradura(elAutomata.getNodoInicial(), new ListaNodos());

        for (int i = 0; i < cadena.length(); i++) {
            String token = cadena.substring(i, i + 1);
            ListaNodos mover = SubConjunto.mover(s, new Token(token));
            if (mover == null) {
                return false;
            }
            camino += String.valueOf("[" + mover.imprimirPath()+"]    ");
            s = SubConjunto.e_cerradura(mover);
        }
        camino += "\n";
        return s.contieneFinal();
    }

    /**
     * Simula, dada una cadena de entrada, el AFD o el AFDmin que se representa por la propiedad
     * elAutomata
     * @param cadena entrada para la simulacion
     * @return true si la cadena pertenece al AFD, false en caso contrario
     */
    private boolean simularAFD(String cadena) {
        Nodo actual = elAutomata.getNodoInicial();
        camino = "\nCamino: ";

        for (int i = 0; i < cadena.length(); i++) {
            String token = cadena.substring(i, i + 1);
            actual = actual.nodoDestino(new Token(token));
            if (actual == null) {
                return false;
            }
            camino += String.valueOf(actual.toString()) + "    ";
        }
        camino += "\n";
        return elAutomata.getNodosFinales().contiene(actual);
    }

    public String getCamino(){
        return this.camino;
    }

    public void setCamino(String camino){
        this.camino = camino;
    }
}
